﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MyX.Core;
using MyX.Message;
using MyX.Bus;
using MyX.Work;
using System.Threading;
using MyX.Store;
using MyX.Provider;
using System.Collections.Concurrent;

namespace MyX
{
    public class XClient
    {
        static XClient()
        {
            _factory = new XFactory();           
        }

        public static XIFactory Factory { get { return _factory; } }

        public static XIMQ XMQ { get { return ServiceLocator.Get<XIMQ>(); } }

        internal static XIMessageBus CommandBus { get { return ServiceLocator.Get<XIMessageBus>("command_bus"); } }
        internal static XIMessageBus EventBus { get { return ServiceLocator.Get<XIMessageBus>("event_bus"); } }
        internal static XIMessageBus StausBus { get { return ServiceLocator.Get<XIMessageBus>("status_bus"); } }
        internal static XIMessageBus ResultBus { get { return ServiceLocator.Get<XIMessageBus>("result_bus"); } }

        internal static XIEntityObserver SaveObserver { get { return ServiceLocator.Get<XIEntityObserver>("save_observer"); } }

        internal static XIEntityObserver SendObserver { get { return ServiceLocator.Get<XIEntityObserver>("send_observer"); } }

        public static XIEventRepository EventRepository { get { return ServiceLocator.Get<XIEventRepository>("event_repository"); } }
        public static XICommandRepository CommandRepository { get { return ServiceLocator.Get<XICommandRepository>("command_repository"); } }

        private static XFactory _factory;
    }

    public static class XMessageHelper
    {
        /// <summary>
        /// 发送事件
        /// </summary>
        /// <param name="e"></param>
        public static void Send(this XEvent e)
        {
            XClient.EventBus.Send(e);
        }

        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="c"></param>
        public static void Send(this XCommand c)
        {
            XClient.CommandBus.Send(c);
        }

        /// <summary>
        /// 将事件重放
        /// </summary>
        /// <param name="e"></param>
        public static void Replay(this XEvent e)
        {
            XReplayManage.Replay(e);
        }

        public static async Task<object> Result(this XIMessage message)
        {
            var source = new CancellationTokenSource(1000);
            var token = source.Token;

            var task = Task.Factory.StartNew(
                () =>
                {
                    while (true)
                    {
                        if (token.IsCancellationRequested)
                            break;
                        token.WaitHandle.WaitOne(10);

                        var result = WorkResult.ContainsKey(message.ID);
                        if (result)
                            break;
                    }
                }, token);

            await task;
            XWorkResult workResult = null;
            WorkResult.TryGetValue(message.ID, out workResult);
            return workResult.Result;
        }

        public static void SetResult(this XIMessage message, object result)
        {
            var workResult = new XWorkResult(message.ID, result);
            XClient.ResultBus.Send(workResult);
        }

        /// <summary>
        /// 得到命令执行状态
        /// <para>在多个方法响应命令的情况下，可能取到不同的状态</para>
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static async Task<XWorkStatus> Status(this XIMessage message)
        {
            await Wait(message);


            XWorkStatus result = null;
            var isGet = WorkStatus.TryGetValue(message.ID, out result);
            if (!isGet)
                throw new Exception("未能获取状态信息");

            return result;
        }

        /// <summary>
        /// 等待命令执行完成
        /// <para>在多个方法响应命令的情况下，可能取到不同的状态</para>
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        private static async Task Wait(this XIMessage message)
        {
            var source = new CancellationTokenSource(1000);
            var token = source.Token;

            var task = Task.Factory.StartNew(
                () =>
                {
                    while (true)
                    {
                        if (token.IsCancellationRequested)
                            break;

                        //以后可以考虑，获取消息结果，因为现在状态消息有处理状态等各种属性值1！！！！
                        token.WaitHandle.WaitOne(10);

                        //以后可以考虑，获取消息结果，因为现在状态消息有处理状态等各种属性值11111！！！
                        var result = WorkStatus.ContainsKey(message.ID);
                        if (result)
                            break;
                    }
                }, token);

            await task;
        }

        internal static ConcurrentDictionary<Guid, XWorkResult> WorkResult = new ConcurrentDictionary<Guid, XWorkResult>();
        internal static ConcurrentDictionary<Guid, XWorkStatus> WorkStatus = new ConcurrentDictionary<Guid, XWorkStatus>();
    }
}
